// phalanx rbegin.hpp.cu header file

// Copyright (c) 2011 - 2011 Kohei Takahashi (Flast).
// Distributed under the MIT license. for more detail see COPYING.

#ifndef IG_PHALANX_UTILITY_DETAIL_RBEGIN_HPP_CU_ONCE_
#define IG_PHALANX_UTILITY_DETAIL_RBEGIN_HPP_CU_ONCE_

#include <phalanx/config.hpp.cu>

#include <cstddef>

#include <phalanx/functional/size.hpp.cu>

#include <phalanx/iterator/reverse_iterator.hpp.cu>
#include <phalanx/iterator/builtin_vector_iterator.hpp.cu>

#include <phalanx/type_traits/builtin_traits.hpp.cu>
#include <phalanx/type_traits/remove_const.hpp.cu>

#include <phalanx/utility/enable_if.hpp.cu>

namespace phalanx
{

// for sequence
template < typename Sequence >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename disable_if<
  is_builtin_vector< Sequence >,
  typename Sequence::reverse_iterator >::type
rbegin( Sequence &seq )
{ return seq.rbegin(); }

template < typename Sequence >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename disable_if<
  is_builtin_vector< Sequence >,
  typename Sequence::const_reverse_iterator >::type
rbegin( const Sequence &seq )
{ return seq.rbegin(); }

template < typename Sequence >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename disable_if<
  is_builtin_vector< Sequence >,
  typename Sequence::const_reverse_iterator >::type
crbegin( const Sequence &seq )
{ return rbegin( seq ); }

// for CUDA builtin vector types
template < typename vector >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename enable_if<
  is_builtin_vector< typename remove_const< vector >::type >,
  reverse_iterator< builtin_vector_iterator< vector > > >::type
rbegin( vector &vec )
{
    typedef builtin_vector_iterator< vector > iterator;
    return reverse_iterator< iterator >( iterator( vec, size( vec ) ) );
}

template < typename vector >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename enable_if<
  is_builtin_vector< vector >,
  reverse_iterator< builtin_vector_iterator< const vector > > >::type
crbegin( const vector &vec )
{ return rbegin( vec ); }

// for array
template < typename T, ::std::size_t n_ >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
reverse_iterator< T * >
rbegin( T ( &_array )[ n_ ] )
{ return reverse_iterator< T * >( _array + n_ ); }

template < typename T, ::std::size_t n_ >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
reverse_iterator< const T * >
crbegin( const T ( &_array )[ n_ ] )
{ return rbegin( _array ); }

} // namespace phalanx

#endif // IG_PHALANX_UTILITY_DETAIL_RBEGIN_HPP_CU_ONCE_

